package com.cjd.common.adapter

import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.cjd.common.R
import com.cjd.common.holder.BaseRecyclerHolder
import com.cjd.common.holder.LoadMoreRecyclerHolder
import java.util.*

/**
 * @Author chenjidong
 * @email 374122600@qq.com
 * created 2017/7/7
 * description 底部加载更多、重试、最后一条数据提示
 * tips: 监听滚动状态 {@link OnRecyclerLoadMoreScrollListener}
 */
abstract class BaseRecyclerLoadMoreAdapter<T> : BaseRecyclerArrayAdapter<T, BaseRecyclerHolder>() {

    companion object {
        protected const val VIEW_TYPE_FOOTER = -1

    }

    protected var mStatus = LoadMoreStatus.INVISIBLE
    private var onRetryViewClickListener: (() -> Unit)? = null
    private var onItemViewClickListener: ((view: View, pos: Int) -> Unit)? = null

    protected var mIsStaggered = false
    private var moreText: String? = null

    protected abstract fun onCreateItemViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): BaseRecyclerHolder

    protected abstract fun onBindItemViewHolder(holder: BaseRecyclerHolder, position: Int)

    /**
     * 最后一行加载更多 单独占用一行
     *
     * @param pos
     * @return
     */
    protected open fun isSingleRow(pos: Int): Boolean {
        return pos == itemCount - 1 && mStatus != LoadMoreStatus.INVISIBLE
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerHolder {
        return if (viewType == VIEW_TYPE_FOOTER) {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.base_recycler_load_more, parent, false)
            LoadMoreRecyclerHolder(view)
        } else {
            val holder = onCreateItemViewHolder(parent, viewType)
            //todo 自定义recyclerView 时不设置点击事件 避免 事件冲突
            onItemViewClickListener?.let { listener ->
                holder.itemView.setOnClickListener { view -> listener.invoke(view, holder.layoutPosition) }
            }
            holder
        }
    }

    override fun onBindViewHolder(holder: BaseRecyclerHolder, position: Int) {
        when (getItemViewType(position)) {
            VIEW_TYPE_FOOTER -> {
                val loadMoreHolder = holder as LoadMoreRecyclerHolder
                checkStaggered(loadMoreHolder)
                when (mStatus) {
                    LoadMoreStatus.INVISIBLE -> {
                    }
                    LoadMoreStatus.MORE -> {
                        loadMoreHolder.button.visibility = View.GONE
                        loadMoreHolder.progressBar.visibility = View.VISIBLE
                    }
                    LoadMoreStatus.END -> {
                        loadMoreHolder.progressBar.visibility = View.GONE
                        loadMoreHolder.button.visibility = View.VISIBLE
                        loadMoreHolder.button.isEnabled = false
                        loadMoreHolder.button.setOnClickListener(null)
                        if (TextUtils.isEmpty(moreText))
                            loadMoreHolder.button.setText(R.string.base_load_end)
                        else
                            loadMoreHolder.button.text = moreText
                    }
                    LoadMoreStatus.RETRY -> {
                        loadMoreHolder.progressBar.visibility = View.GONE
                        loadMoreHolder.button.visibility = View.VISIBLE
                        loadMoreHolder.button.isEnabled = true
                        loadMoreHolder.button.setText(R.string.base_load_retry)
                        loadMoreHolder.button.setOnClickListener {
                            notifyLoadMoreData()
                            onRetryViewClickListener?.invoke()
                        }
                    }
                }
            }
            else -> {
                onBindItemViewHolder(holder, position)
            }
        }
    }

    fun setOnRetryListener(listener: (() -> Unit)) {
        onRetryViewClickListener = listener
    }

    fun setOnViewClickListener(listener: ((view: View, pos: Int) -> Unit)) {
        onItemViewClickListener = listener
    }

    fun notifyLoadMoreOrWholeData(data: Collection<T>?, page: Int = 1, size: Int = 20) {
        if (page == 1)
            replaceAll(data ?: Collections.emptyList())
        else
            addAll(data)

        if (data == null || data.isEmpty() || data.size < size) {
            notifyLoadWholeData()
        }else
            notifyLoadMoreData()
    }

    fun notifyLoadMoreData() {
        mStatus = LoadMoreStatus.MORE
        notifyItemChanged(itemCount - 1)
    }

    fun notifyLoadWholeData() {
        mStatus = LoadMoreStatus.END
        notifyItemChanged(itemCount - 1)
    }

    fun notifyLoadWholeData(text: String) {
        moreText = text
        mStatus = LoadMoreStatus.END
        notifyItemChanged(itemCount - 1)
    }

    fun notifyLoadMoreData(size: Int) {
        mStatus = LoadMoreStatus.MORE
        notifyItemRangeChanged(size, itemCount - 1)
    }

    fun notifyLoadWholeData(size: Int) {
        mStatus = LoadMoreStatus.END
        notifyItemRangeChanged(size, itemCount - 1)
    }

    fun notifyLoadWrong() {
        mStatus = LoadMoreStatus.RETRY
        notifyItemChanged(itemCount - 1)
    }

    fun hideProgress() {
        mStatus = LoadMoreStatus.INVISIBLE
        notifyDataSetChanged()
    }

    fun hasMoreData(): Boolean {
        return mStatus == LoadMoreStatus.MORE || mStatus == LoadMoreStatus.RETRY
    }

    fun getItemSize(): Int {
        return currentItems.size
    }

    override fun getItemCount(): Int {
        return if (mStatus == LoadMoreStatus.INVISIBLE)
            super.getItemCount()
        else
            super.getItemCount() + 1
    }

    override fun getItemViewType(position: Int): Int {
        return if (position == itemCount - 1 && mStatus != LoadMoreStatus.INVISIBLE) VIEW_TYPE_FOOTER else super.getItemViewType(
            position
        )
    }

    /**
     * 瀑布流 确保底部加载更多样式 不损坏
     *
     * @param loadMoreHolder
     */
    private fun checkStaggered(loadMoreHolder: LoadMoreRecyclerHolder) {
        if (mIsStaggered)
            if (loadMoreHolder.itemView.layoutParams is StaggeredGridLayoutManager.LayoutParams) {
                val lp =
                    loadMoreHolder.itemView.layoutParams as StaggeredGridLayoutManager.LayoutParams
                if (!lp.isFullSpan)
                    lp.isFullSpan = true
            }
    }

    enum class LoadMoreStatus {

        INVISIBLE, MORE, END, RETRY

    }

}